package com.health.viewscontrols;

import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Environment;
import android.os.Looper;
import android.os.SystemClock;
import android.text.TextUtils;
import android.util.Log;
import android.widget.Toast;
import com.blankj.utilcode.util.LogUtils;
import com.blankj.utilcode.util.NetworkUtils;
import com.health.tools.GlobalConts;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
import io.reactivex.functions.Consumer;
import rxhttp.RxHttp;

/**
 * @author xiaoxin
 * @date 2017/1/19
 * @describe ：异常处理类
 * 修改内容
 */

public class CrashHandler implements Thread.UncaughtExceptionHandler {

	private static final String TAG = CrashHandler.class.getSimpleName();

	private static final boolean DEBUG = true;
	private static final String FILE_PATH = Environment.getExternalStorageDirectory().getPath()+ "/EhrApp/log";
	private static final String FILE_NAME = "crash";

	//log文件的后缀名
	private static final String FILE_SUFFIX = ".txt";

	private static CrashHandler mCrashHandler;

	//系统默认的异常处理(默认情况下，系统会终止当前的异常程序)
	private Thread.UncaughtExceptionHandler mUncaughtExceptionHandler;

	private Context mContext;

	private CrashHandler() {

	}

	public static CrashHandler getInstance() {
		if (mCrashHandler == null) {
			synchronized (CrashHandler.class) {
				if (mCrashHandler == null) {
					mCrashHandler = new CrashHandler();
				}
			}
		}

		return mCrashHandler;
	}

	public void init(Context context) {
		//获取系统默认的异常处理器
		mUncaughtExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
		//将当前实例设为系统默认的异常处理器
		Thread.setDefaultUncaughtExceptionHandler(this);
		mContext = context.getApplicationContext();
	}

	/**
	 * 这个是最关键的函数，当程序中有未被捕获的异常，系统将会自动调用uncaughtException方法
	 * thread为出现未捕获异常的线程，ex为未捕获的异常，有了这个ex，我们就可以得到异常信息。
	 */
	@Override
	public void uncaughtException(Thread t, Throwable ex) {
		try {
			//toast提示用户程序crash掉了
			//handleException(ex);


			saveErrorInfo(ex);
			//这里可以通过网络上传异常信息到服务器，便于开发人员分析日志解决bug
			uploadExceptionToServer();
			//导出异常信息到SD卡中
			dumpExceptionToSDCard(ex);
			SystemClock.sleep(2000);
		} catch (Exception e) {
			e.printStackTrace();
		}

		//打印出当前调用栈信息
		//ex.printStackTrace();

		//如果系统提供了默认的异常处理器，则交给系统去结束我们的程序，否则就由我们自己结束自己
		if (mUncaughtExceptionHandler != null) {
			mUncaughtExceptionHandler.uncaughtException(t, ex);
		} else {
//            Process.killProcess(Process.myPid());
//            Intent intent = new Intent(mContext.getApplicationContext(), SplashActivity.class);
//            @SuppressLint("WrongConstant") PendingIntent restartIntent = PendingIntent.getActivity(
//            		mContext.getApplicationContext(), 0, intent,
//                    Intent.FLAG_ACTIVITY_NEW_TASK);
//            //退出程序
//            AlarmManager mgr = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);
//            mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 1000,
//                    restartIntent); // 1秒钟后重启应用
		}
		//showDialog();

	}

	/**
	 * 自定义错误处理,收集错误信息 发送错误报告等操作均在此完成.
	 *
	 * @param ex
	 * @return true:如果处理了该异常信息;否则返回false.
	 */
	private boolean handleException(Throwable ex) {
		if (ex == null) {
			return false;
		}
		//使用Toast来显示异常信息
		new Thread() {
			@Override
			public void run() {
				Looper.prepare();
				Toast.makeText(mContext, "很抱歉,程序出现异常,即将退出.", Toast.LENGTH_LONG).show();
				Looper.loop();
			}
		}.start();
		return true;
	}

	private void dumpExceptionToSDCard(Throwable ex) throws IOException {
		//如果SD卡不存在或无法使用，则无法把异常信息写入SD卡
		if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
			if (DEBUG) {
				Log.e(TAG, "dumpExceptionToSDCard: " );
				return;
			}
		}

		String time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(
				new Date(System.currentTimeMillis()));

		//以当前时间创建log文件
		//File file = new File(FILE_PATH + FILE_NAME + time + FILE_SUFFIX);
//        File file = new File(Environment.getExternalStorageDirectory()+"/MyApp/logCrash/",
//                "aaaaa.xml");
		File file1 = new File(FILE_PATH);
		File file = new File(FILE_PATH + FILE_NAME + time + FILE_SUFFIX);
		if (!file1.exists()) {
			file1.mkdirs();
		}
		if (!file.exists()) {
			file.createNewFile();
		}

		try {
			PrintWriter printWriter = new PrintWriter(new BufferedWriter(new FileWriter(file)));

			//导出发生异常的时间
			printWriter.println(time);

			//导出手机信息
			dumpPhoneInfo(printWriter);

			printWriter.println();
			//导出异常的调用栈信息
			ex.printStackTrace(printWriter);
			printWriter.close();
		} catch (Exception e) {
			Log.e(TAG, "dump crash info failed");
		}
	}

	private void saveErrorInfo(Throwable throwable) {
//        String username = Hawk.get(Constant.LOGIN_NAME, "");

		StringBuffer stringBuffer = new StringBuffer();
		stringBuffer.append(getAppInfo(mContext));
		stringBuffer.append("崩溃时间：").append(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())).append("\n");
//        stringBuffer.append("登录账号：").append(username + "").append("\n");
		stringBuffer.append("网络类型：").append(NetworkUtils.getNetworkType() + "").append("\n");
		stringBuffer.append("手机系统：").append(Build.VERSION.RELEASE).append("\n");
		stringBuffer.append("手机型号：").append(Build.MODEL + "(" + Build.BRAND + ")").append("\n");
		stringBuffer.append("CPU ABI: ").append(Build.CPU_ABI).append("\n");
		StringWriter sw = new StringWriter();
		PrintWriter pw = new PrintWriter(sw);
		throwable.printStackTrace(pw);
		stringBuffer.append("崩溃信息：").append(sw.toString());
		Log.e(TAG, "saveErrorInfo: " + stringBuffer.toString() );
//		uploadMsg(stringBuffer.toString());
		uploadMsg1(stringBuffer.toString());
	}

	public static void uploadMsg1(String msg) {
		try {
			RxHttp.postJson(GlobalConts.URL_SHOUQUAN_ADDRESS + "android/log/addLog")
					.add("loginfo", msg)
					.addHeader("Content-Type","application/json")
					.asString()
					.subscribe(new Consumer<String>() {
						@Override
						public void accept(String s) throws Exception {

						}
					}, throwable1 -> {

					});

		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static void uploadMsg(String msg) {
		try {
			String messageStr = messageStr(msg, "18254198695");
			RxHttp.postJson("https://oapi.dingtalk.com/robot/send?access_token=10c7f34b56b9be93ef99066d98f4032e3435db25529c4e1596658c07a9a3edeb")
					.addAll(messageStr)
					.addHeader("Content-Type","application/json")
					.asString()
					.subscribe(new Consumer<String>() {
						@Override
						public void accept(String s) throws Exception {

						}
					}, throwable1 -> {

					});

		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 构造钉钉消息格式
	 * @param message 内容
	 * @return
	 */
	public static String messageStr(String message,String phone) {
		if(TextUtils.isEmpty(message)) {
			throw new IllegalArgumentException("message should not be blank");
		}
		JSONObject jsonObject = new JSONObject();
		try {
			jsonObject.put("msgtype", "text");
			JSONObject jsonObject1 = new JSONObject();
			jsonObject1.put("content", "健康管理\n"+message);
			jsonObject.put("text", jsonObject1.toString());

			JSONArray jsonArray = new JSONArray();
			jsonArray.put(phone);
			JSONObject atJson = new JSONObject();
			atJson.put("atMobiles",jsonArray);
			atJson.put("isAtAll",false);
			jsonObject.put("at",atJson);

		} catch (JSONException e) {
			e.printStackTrace();
		}
		return jsonObject.toString();
	}

	/**
	 * 获取应用程序信息
	 */
	public String getAppInfo(Context context) {
		try {
			PackageManager packageManager = context.getPackageManager();
			PackageInfo packageInfo = packageManager.getPackageInfo(context.getPackageName(), 0);
			return "应用包名：" + packageInfo.packageName + "\n应用版本：" + packageInfo.versionName + "\n";
		} catch (Exception e) {
			e.printStackTrace();
		}
		return "";
	}

	private void uploadExceptionToServer() {
		//TODO :如果需要把crash文件上传至服务器，在这里操作.

	}

	private void dumpPhoneInfo(PrintWriter printWriter) throws
			PackageManager.NameNotFoundException {

		//应用的版本名称和版本号
		PackageManager packageManager = mContext.getPackageManager();
		PackageInfo packageInfo = packageManager.getPackageInfo(
				mContext.getPackageName(), PackageManager.GET_ACTIVITIES);

		printWriter.print("App Version: ");
		printWriter.print(packageInfo.versionName);
		printWriter.print('_');
		printWriter.println(packageInfo.versionCode);

		//Android版本号
		printWriter.print("OS Version: ");
		printWriter.print(Build.VERSION.RELEASE);
		printWriter.print("_");
		printWriter.println(Build.VERSION.SDK_INT);

		//手机制造商
		printWriter.print("Vendor: ");
		printWriter.println(Build.MANUFACTURER);

		//手机型号
		printWriter.print("Model: ");
		printWriter.println(Build.MODEL);

		//CPU架构
		printWriter.print("CPU ABI: ");
		printWriter.println(Build.CPU_ABI);
	}
}
